import core from '@/core/'
// #ifdef H5
import * as XLSX from 'xlsx/dist/xlsx.core.min'
// #endif

/**
 * 读取本地Excel表格
 * 微信小程序没有new FileReader()
 */
const analyseExcelFile = (file) => {
    var fileReader = new FileReader()
    fileReader.readAsBinaryString(file)
    return new Promise(function(resolve, reject) {
        fileReader.onload = function (ev) {
            try {
                var data = ev.target.result
                var workbook = XLSX.read(data, {
                    type: 'binary'
                }) // 以二进制流方式读取得到整份excel表格对象
                var fromTo = '';
                var sheetContent = []
                // 遍历每张表读取
                for (var sheet in workbook.Sheets) {
                    if (workbook.Sheets.hasOwnProperty(sheet)) {
                        fromTo = workbook.Sheets[sheet]['!ref'];
						const obj = workbook.Sheets[sheet]
						Object.keys(obj).forEach(key => {
							if (typeof(obj[key]) == "object") {
								Object.keys(obj[key]).forEach(k => {
									// 去除注释信息
									if (key.substr(key.length - 1, 1) === '1') {
										if (k === 'v') {
											const value = obj[key].v
											if (value && value.length > 2) {
												if (value.substr(value.length - 1, 1) === ']') {
													if (value.indexOf('[') > -1) {
														obj[key].v = value.split('[')[0]
													}
												}
											}
										}
									} else {
										// 日期格式化 - 会统一转化为YYYY-MM-DD hh:mm:ss
										if (k === 'z' &&  obj[key].z === 'm/d/yy') {
											obj[key].v = formatDate(obj[key].v,  '-')
											delete obj[key].z
										}
									}
								})
							}
						})
                        sheetContent.push(XLSX.utils.sheet_to_json(workbook.Sheets[sheet]))
                        // break; // 如果只取第一张表，就取消注释这行
                    }
                }
                resolve(sheetContent)
            } catch (e) {
                reject('解析失败')
            }
        }
    })
}

//excel日期格式转换 numb为得到的数字，但是为何相差8小时43秒！
const formatDate = (numb) => {
	if (numb) {
		// 减去08:00:43
		const date = new Date((numb - 1) * 24 * 3600000 + 1 - (8 * 60 * 60 + 43) * 1000)
		return core.time.getString(date)
	}
	return ''
}

/**
 * excel的读和写
 */
module.exports = {
	/**
	 * 先选择文件
	 * 然后解析文件
	 */
	read() {
		return new Promise((resolve, reject) => {
			var fcname
			// #ifdef MP-WEIXIN
			fcname = 'chooseMessageFile'
			// #endif
			// #ifdef H5
			fcname = 'chooseFile'
			// #endif
			if (fcname) {
				uni[fcname]({
					count: 1,
					extension: ['.xls', '.xlsx'],
					success(res) {
						// #ifdef H5
						analyseExcelFile(res.tempFiles[0]).then(resolve).catch(reject)
						// #endif
						// #ifdef MP-WEIXIN
						core.showToast('还不能解析excel')
						// #endif
					},
					fail(err) {
						reject(err)
					}
				})
			} else {
				reject('没有相关的API')
			}
		})
	},
	
	/**
	 * 写入数据，得到excel文件
	 * H5通过download-excel可自动得到
	 */
	write({
		type = 'xls', // 文件类型 xls或者csv
		data =  undefined, // Array 需要导出的数据 - 固定数据
		fetch = undefined, // Function 需要导出的数据 - Promise返回数据。data不存在时生效
		fields =  undefined, // Object 要导出的JSON对象中的字段，如果没有提供，JSON中的所有属性将被导出
		exportFields = undefined, // 在这里没有使用 // Object 解决与其他组件的命名冲突问题，用于解决使用变量字段的其他组件（如 vee-validate）的问题。导出字段的工作原来与字段完全相同，
		name = '导出文件', // 导出的文件名称
		header = '', // String, Array 表格的标题。可以是字符串（一个标题）或字符串数组（多个标题）
		footer = '', // String, Array 表格的页脚。可以是字符串（一个页脚）或字符串数组（多个页脚）
		worksheet = '', // String 工作表选项卡的名称
		defaultValue = '-', // 如果某一行没有字段值时候起作用，当行没有字段值时用作回退
		stringifyLongNum = false, // 字符串化长数字和小数（解决数字精度损失的问题），默认值：false
		escapeCsv = true, // 这将转义CSV值，以修复一些excel数字字段的问题。但这会用=" and "包装所有csv数据，以避免你不得不将这个道具设为假。默认值:true
		beforeGenerate = undefined, // Function 在生成/获取数据之前调用方法，例如:显示加载进度
		beforeFinish = undefined, // Function 在下载框弹出之前调用方法的回调，例如:隐藏加载进度
	} = {}) {
		
		const handleData = () => {
			// 表头，数据
			const tableHeaders = fields ? Object.keys(fields) : [], tableData = []
			if (!fields) {
				if (data.length > 0) {
					if (typeof(data[0]) === 'string') {
						// 没有表头
						data.map(item => {
							tableData.push(item)
						})
					} else {
						Object.keys(data[0]).forEach(key => {
							// 添加第一个数据的key为表头
							tableHeaders.push(key)
						})
					}
				}
			}
			data && data.map(item => {
				var content
				if (Array.isArray(item)) {
					content = item
				} else {
					content = []
					for (let i = 0; i < tableHeaders.length; i++) {
						if (fields) {
							const key = tableHeaders[i]
							// 有表头的。获取表头数据
							if (typeof(fields[key]) === 'string') {
								content.push(item[fields[key]])
							} else {
								const {field, callback} = fields[key]
								if (field) {
									// 必须有field。经过反复测试，小程序不支持callback。不建议如此传递
									content.push(callback ? callback(item[field], item) : item[field])
								} else {
									content.push(defaultValue)
								}
							}
						} else {
							// 没有表头的，自动获取的表头
							content.push(item[tableHeaders[i]])
						}
					}
				}
				tableData.push(content)
			})
			const sheetData = XLSX.utils.aoa_to_sheet([tableHeaders, ...tableData])
			const workbook = XLSX.utils.book_new()
			// 创建工作簿
			XLSX.utils.book_append_sheet(workbook, sheetData, worksheet)
			// 创建表格数据
			const fileData = XLSX.write(workbook, {
				bookType: "xlsx",
				type: 'base64'
			})
			const fileName = (name || '导出文件') + '.xlsx'
			const newFilePath = uni.env.USER_DATA_PATH + '/' + fileName // 文件名对应表名，多个表的情况可以自己测试
			const fs = uni.getFileSystemManager()
			fs.writeFile({
				filePath: newFilePath,
				data: fileData,
				encoding: 'base64',
				success: res => {
					const sysInfo = uni.getSystemInfoSync()
					if (sysInfo.platform.toLowerCase().indexOf('windows') >= 0) {
						uni.saveFileToDisk({
							filePath: newFilePath,
							success: console.log,
							fail: console.error
						})
					} else {
						uni.openDocument({
							filePath: newFilePath,
							showMenu: true, // 需要添加showMenu允许用户导出
							success: console.log,
							fail: console.error
						})
					}
				},
				fail: e => {
					if (e.errMsg.indexOf('locked')) {
						wx.showModal({
							title: '提示',
							content: '文档已打开，请先关闭',
						})
					}
				}
			})
			// H5可直接导出文件
			// XLSX.writeFile(workbook, fileName)
		}
		
		if (fetch) {
			// 网络请求，获取数据
			fetch().then(res => {
				data = res
				handleData()
			})
		} else {
			handleData()
		}
	}
}